#include "shader.h"

bool
eTB_Shader::Compile (void)
{
  if (handle_ == 0)
    return false;

  glShaderSource (handle_, 1, &source_, NULL);

  /* Shader Source Error. */
  if (glGetError () != GL_NO_ERROR)
    return false;

  glCompileShader (handle_);

  if (glGetError () != GL_NO_ERROR)
    return false;

  GLint compile_status = GL_FALSE;
  glGetShaderiv (handle_, GL_COMPILE_STATUS, &compile_status);

  if (compile_status == GL_FALSE)
    return false;

  return true;
}

eStringA
eTB_Shader::GetLog (void)
{
  GLint string_len;
  glGetShaderiv (handle_, GL_INFO_LOG_LENGTH, &string_len);

  char* log = new char [string_len + 1];

  glGetShaderInfoLog (handle_, string_len + 1, NULL, log);

  eStringA log_str (log);

  delete [] log;

  return log_str;
}

eTB_Shader*
eTB_ShaderFactory::createShaderFromFile ( const char*      szFileName,
                                          const char*      szName,
                                          eTB_Shader::Type type )
{
  eDiskFile file;

  eStringA file_name (szFileName);
  
  if (! file.open (file_name, _T ("rbS"))) {
    printf ("No such file : %s\n", szFileName);
    return NULL;
  }

  eTB_Shader* pShader =
    createShaderFromOpenFile (&file, file.size (), szName, type);

  if (! pShader)
    return NULL;

  file.close ();

  return pShader;
}

eTB_Shader*
eTB_ShaderFactory::createShaderFromOpenFile ( eFile*           file,
                                              eFileSize        size,
                                              const char*      szName,
                                              eTB_Shader::Type type )
{
  if (! file)
    return NULL;

  char* szSourceCode = new char [size + 1];

  if (file->read (szSourceCode, 1, size) != size) {
    /* Requested shader could not be read, or the length was wrong... */
    return NULL;
  }

  /* Do not forget the NULL terminator. */
  szSourceCode [size] = '\0';

  eTB_Shader* pShader =
    createShaderFromString (szSourceCode, szName, type);

  delete [] szSourceCode;

  return pShader;
}

eTB_Shader*
eTB_ShaderFactory::createShaderFromString ( const char*      szSourceCode,
                                            const char*      szName,
                                            eTB_Shader::Type type )
{
  eTB_Shader* pShader = NULL;

  switch (type) {
    case eTB_Shader::Vertex:
      pShader          = new eTB_VertexShader (szName);
      pShader->source_ = strdup (szSourceCode);
      break;
    case eTB_Shader::Pixel:
      pShader          = new eTB_PixelShader (szName);
      pShader->source_ = strdup (szSourceCode);
      break;
    default:
      /* Only Vertex and Pixel For Now... */
      return NULL;
  }

  return pShader;
}

